package org.tony.spider.common;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Properties;
import java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;
import org.tony.spider.book.Book;
import org.tony.spider.book.ChapterInfo;
import org.tony.spider.zhulang.QueryBookDetailRunner;

public abstract class QueryBookCatalogue
{

  protected String          saveDir       = "d:\\data\\";
  protected ExecutorService pool;
  protected String[]        selectLables;
  protected String          vipTag        = "vip";
  protected String          chapterRegTag = "\u7B2C.+\u7AE0.+";
  protected String          baseUrl;
  protected GetRequestor    getReq;

  protected void init()
  {
    getReq = new GetRequestor();
    initExtraInfo();
  }

  protected abstract void initExtraInfo();

  public QueryBookCatalogue(String[] selectLabels)
  {
    this.selectLables = selectLabels;
    pool = Executors.newFixedThreadPool(20);
    init();
  }

  public void query(Book bookInfo)
  {
    Stack<String> vipChapters = new Stack<String>();
    int count = 0;
    String content = getReq.startGet(bookInfo.getBookHomePage());
    Document doc = Jsoup.parse(content);
    Elements eles = null;
    Elements temp = null;
    for (int i = 0; i < selectLables.length; i++)
    {
      if (i == 0)
      {
        temp = doc.select(selectLables[i]);
      }
      else
      {
        temp = temp.select(selectLables[i]);
      }
    }
    eles = temp;
    for (Iterator<Element> eleIter = eles.iterator(); eleIter.hasNext();)
    {
      Element ele = eleIter.next();
      if (ele.childNodes().size() > 0)
      {

        Node textNode = ele.childNode(0);
        String url = ele.attr("href");
        String text = textNode.attr("text");

        if (text.matches(chapterRegTag))
        {
          count++;
          if (!url.contains(vipTag))
          {
            if (!url.startsWith("http"))
            {
              url = this.baseUrl + url;
            }
            ChapterInfo ci = new ChapterInfo();
            ci.setIsVip(false);
            ci.setTitle(String.format("(%d) %s", count, text));
            ci.setSavePath(saveDir + bookInfo.getBookName() + File.separator + ci.getTitle() + ".txt");
            ci.setUrl(url);
            ci.setBook(bookInfo);
            QueryBookDetailRunner qbdr = new QueryBookDetailRunner(ci);
            pool.execute(qbdr);
          }
          else
          {
            try
            {
              vipChapters.push(String.format("(%d) %s", count, URLEncoder.encode(text, "GB2312")));
            }
            catch (UnsupportedEncodingException e)
            {
              e.printStackTrace();
            }
          }
        }

      }
    }
    if (!vipChapters.empty())
    {
      FileUtil.writeUnDownChpaters(vipChapters, saveDir + bookInfo.getBookName()
          + "\\un_download_chapter.data");
    }
    pool.shutdown();
  }

  protected void writeBookInfoToFile(Book book, Properties catalogue)
  {
    catalogue.put("book-name", book.getBookName());
    catalogue.put("init-loading", "true");
    FileUtil.storeProps(catalogue, book.getBookCataloguePath());
  }

  public String getSaveDir()
  {
    return saveDir;
  }

  public void setSaveDir(String saveDir)
  {
    this.saveDir = saveDir;
  }

  public String getVipTag()
  {
    return vipTag;
  }

  public void setVipTag(String vipTag)
  {
    this.vipTag = vipTag;
  }

  public String getChapterRegTag()
  {
    return chapterRegTag;
  }

  public void setChapterRegTag(String chapterRegTag)
  {
    this.chapterRegTag = chapterRegTag;
  }

  public String getBaseUrl()
  {
    return baseUrl;
  }

  public void setBaseUrl(String baseUrl)
  {
    this.baseUrl = baseUrl;
  }

}
